/****************************************************************************************************
 *****************************************************************************************************
 
 Animated GIF Photobooth by David Boardman (dboardman@ideo.com), Jackie Steck (jsteck@ideo.com)
 "HOW TO SURVIVE THE HOLIDAYS" - PARTY @IDEO NY, 2012
 
 *****************************************************************************************************
 ****************************************************************************************************/

import processing.video.*; 
import processing.serial.*;
import gifAnimation.*; 
import cc.arduino.*;
import fullscreen.*; 
import ddf.minim.*;


Arduino arduino;
Capture cam; 
GifMaker gifExport;
Minim minim;
AudioPlayer audioClick;
FullScreen fs;
PFont font;
PImage[] frameImage=new PImage[5];
String[] cameras;


int frameCounter=0;
int gifDelay=200;
int gifQuality=10; // default=10
int captureWidth=960; //available resolutions: 1920X1080, 1200X675, 960X540, 480X270, 240X135 
int captureHeight=540;
int captureFramerate=30;
int gifWidth=captureWidth;
int gifHeight=captureHeight;


int startTime;
int timeCountdown;
String fileName;
String timeStamp;
Boolean timerSet=false;
Boolean timerFirst=false;
Boolean timerEnd=false;


// SETUP
void setup() { 
  frameRate(30);
  size(1680, 1050);
  
  // Full screen setup
  //fs = new FullScreen(this); 
  //fs.enter();

  // Arduino setup
  arduino = new Arduino(this, Arduino.list()[0], 57600);
  arduino.pinMode(2, Arduino.INPUT);
  arduino.digitalWrite(2, Arduino.HIGH);

  // Webcam capture setup
  cameras = Capture.list();  
  checkCameras();
  cam = new Capture(this, captureWidth, captureHeight, "USB Video Class Video", captureFramerate);
  cam.read();
  createNewGif();

  // Frames images setup
  resetThumbnails();
  // Font
  font = loadFont("FoundersGrotesk.vlw");
  // Audio
  minim = new Minim(this);
  audioClick = minim.loadFile("camera.wav");
} 

// DRAW
void draw() { 
  background(0);
  textFont(font, 90);
  fill(210, 35, 42);
  textAlign(CENTER);
  text("\"ANIMATED GIFs PHOTOBOOTH", width/2, 200);
  checkArduino();
  showThumbnails();
  readCamera();
  setCountdown();
} 


// Minim Library - Stop
void stop() {
  minim.stop();
  super.stop();
}


// Read Webcam
void readCamera() {
  pushMatrix();
  scale(-1, 1);
  image(cam, -1300, 300);
  popMatrix();

  if ((timerFirst) && (timeCountdown==6)) { // 1st shot countdown
    addFrameGif();
    timerFirst=false;
    timerSet=true;
  }
  else if ((!timerFirst) && (timerSet) && (timeCountdown==1)) { // (2nd, 3rd, 4th, 5th shots)
    addFrameGif();
  }
}


// Webcam capture event
void captureEvent(Capture c) {
  c.read();
}

// Countdown shot
void setCountdown() {
  fill(255);
  timeCountdown=(millis()-startTime)/1000;
  // Display timer
  if (timerFirst) {
    if ((timeCountdown>=0)&&(timeCountdown<2)) {
      textFont(font, 100);
      text("Prepare for 5 shots...", width/2, height/2);
    }
    else if (timeCountdown==2) {
      textFont(font, 100);
      text("Ready?", width/2, height/2);
    }
    else if ((timeCountdown>=2)&&(timeCountdown<6)) {
      textFont(font, 200);
      text(6-timeCountdown, width/2, height/2);
    }
  }
  if ((timerEnd)&&(!timerFirst)) {
    if ((timeCountdown>=2)&&(timeCountdown<6)) {
      textFont(font, 60);
      if (!timerSet) text("You look great!\nYour animated portrait is now displayed \n outside.\n\nWant to take another one?", width/2, 400);
    }
    else if (timeCountdown>=6) {
      timerEnd=false;
    }
  }
}


// Add frame GIF
void addFrameGif() {

  if (frameCounter<=4) {  
    playSound();
    frameImage[frameCounter]=cam.get();
    gifExport.addFrame(frameImage[frameCounter]);
    
    startTime = millis();
    frameCounter++;
  }
  else if (frameCounter>4) {
    gifExport.finish();
    resetThumbnails();
    createNewGif();
    timerEnd=true;
    timerSet=false;
  }
}

// Create & setup new GIF
void createNewGif() {
  getFileName();
  gifExport = new GifMaker(this, fileName, gifQuality);
  gifExport.setRepeat(0);
  gifExport.setQuality(gifQuality);
  gifExport.setDelay(gifDelay);
  //gifExport.setSize(gifWidth,gifHeight);
  //gifExport.setTransparent(0,0,0);
}


// Create filename
void getFileName() {
  timeStamp=day()+"-"+month()+"-"+year()+"_"+hour()+minute()+second();
  fileName = "/htdocs/HolidayParty/GIFs/hp_"+timeStamp+".gif";
}


// Check Arduino - Digital Inputs
void checkArduino() {
  if ((arduino.digitalRead(2) == Arduino.LOW) && (frameCounter<5) && (!timerFirst)) {  
    startTime = millis();
    timerFirst=true;
    println("click");
  }
}


void keyPressed() { // Alternative to Arduino-driven push button
  if ((keyCode==32) && (frameCounter<5)) {  
    startTime=millis();
    timerFirst=true;
  }
}


// Thumbnails 5 shots
void showThumbnails() {

  // Display thumbnails frames
  image(frameImage[0], 530, 900, 100, 75);
  image(frameImage[1], 640, 900, 100, 75);
  image(frameImage[2], 750, 900, 100, 75);
  image(frameImage[3], 860, 900, 100, 75);
  image(frameImage[4], 970, 900, 100, 75);

  // Display thumbnails frames numbers
  textFont(font, 24);
  textAlign(CENTER); 
  fill(0);
  text("1", 580, 945);
  text("2", 690, 945);
  text("3", 800, 945);
  text("4", 910, 945);
  text("5", 1020, 945);
}


// Reset Thumbnails 
void resetThumbnails() {
  for (int i=0;i<5;i++) {
    frameImage[i]=loadImage("blank.gif");
  }
  frameCounter=0;
}


//Play Sound
void playSound() {
  audioClick.rewind();
  audioClick.play(); 
  background(255);
}

// List all available cameras / configurations (Debug)
void checkCameras() { 
  if (cameras.length == 0) {
    println("No cameras available for capture.");
    exit();
  } 
  else {
    println("Available cameras:");
    for (int i = 0; i < cameras.length; i++) {
      println(cameras[i]);
    }
  }
}

